#  RAMP Media Organizer  
#  MediaBrowser.py
#
#  Copyright (C) 2010  Vishesh Yadav  
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

""" Media Library Browser GUI

Implements the MediaBrowser widget for displaying the media items
in a good structured form
"""

from PyQt4 import QtGui, QtCore

from Database import Database

class SongModel(QtCore.QAbstractTableModel):
    def __init__(self, parent=None):
        QtCore.QAbstractTableModel.__init__(self, parent)
        self.dataSet = []
        self.songIds = []
        self.columns = ("Title", "Artist", "Album", "Genre")

    def rowCount(self, parent=None):
        return len(self.dataSet)

    def columnCount(self, parent=None):
        return len(self.columns)

    def getSongId(self, row):
        return self.songIds[row]

    def headerData(self, section, orientation, role):
        if role != QtCore.Qt.DisplayRole:
            return None
        if orientation == QtCore.Qt.Horizontal:
            return self.columns[section]

    def data(self, index, role):
        if not index.isValid():
            return None

        if role != QtCore.Qt.DisplayRole:
            return None

        return self.dataSet[index.row()][index.column()]


    def insertRows(self, position, rows, index):
        self.beginInsertRows(QtCore.QModelIndex(), position, position+rows-1)

        for i in range(rows):
            self.dataSet.append( [None, ]*self.columnCount() )
            self.songIds.append( None )
        self.endInsertRows()

        return True


    def setData(self, index, value, role):
        if not index.isValid() or role is not QtCore.Qt.EditRole:
            return False
        self.dataSet[index.row()][index.column()] = value
        self.dataChanged.emit(index, index)
        return True

    def setRow(self, row, data):
        for i in range(self.columnCount()):
            index = self.index(row, i, QtCore.QModelIndex())
            self.setData(index, data[i], QtCore.Qt.EditRole)
            self.songIds[index.row()] = data[-1]

    def clear(self):
        self.beginResetModel()
        self.dataSet = []
        self.songIds = []
        self.endResetModel()


class MediaBrowser(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.db = None

        self.artistList = QtGui.QListWidget()
        self.albumList = QtGui.QListWidget()

        # SongList Table
        self.songModel = SongModel()
        self.songList = QtGui.QTableView()
        self.songList.setModel(self.songModel)
        self.songList.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        self.songList.setShowGrid(False)
        self.songList.horizontalHeader().setStretchLastSection(True)
        #End SongList Table

        self.vsplit = QtGui.QSplitter(QtCore.Qt.Vertical)
        self.hsplit = QtGui.QSplitter(QtCore.Qt.Horizontal)

        self.hsplit.addWidget(self.artistList)
        self.hsplit.addWidget(self.albumList)

        self.vsplit.addWidget(self.hsplit)
        self.vsplit.addWidget(self.songList)

        layout = QtGui.QHBoxLayout()
        layout.addWidget(self.vsplit)
        
        self.setLayout(layout)

        self.setConnections()
        self.ReadGeometrySettings()


    def SaveGeometrySettings(self):
        settings = QtCore.QSettings("ramp-mo", "Vishesh Yadav")
        #Splitter Sizes
        settings.setValue("nbrowser/splitup", self.vsplit.sizes())
        settings.setValue("nbrowser/splitdown", self.hsplit.sizes())
        #SongList Table Column Widths
        settings.setValue("nbrowser/colwidth", 
                [self.songList.columnWidth(x) 
                    for x in range(self.songModel.columnCount())])


    def ReadGeometrySettings(self):
        settings = QtCore.QSettings("ramp-mo", "Vishesh Yadav")

        #Splitter Sizes
        got = [x.toInt()[0] 
                for x in settings.value("nbrowser/splitup").toList()]
        self.vsplit.setSizes(got)
       
        got = [x.toInt()[0] 
               for x in settings.value("nbrowser/splitdown").toList()]
        self.hsplit.setSizes(got)

        #SongList Table Column Widths
        got = [x.toInt()[0] 
                for x in settings.value("nbrowser/colwidth").toList()]
        if not len(got):
            got = [200 for x in range(self.songModel.columnCount())]
        for x in range(self.songModel.columnCount()):
            self.songList.setColumnWidth(x, got[x])


    def setConnections(self):
        self.connect(self.artistList, QtCore.SIGNAL('itemSelectionChanged()'),
            QtCore.SLOT('UpdateAlbums()') )
        self.connect(self.albumList, QtCore.SIGNAL('itemSelectionChanged()'),
            QtCore.SLOT('UpdateTitles()') )
        
        # SongList. 
        selectionModel = QtGui.QItemSelectionModel(self.songModel)
        self.connect(selectionModel, 
            QtCore.SIGNAL('''currentChanged(const QModelIndex &, 
                const QModelIndex &)'''),
            self.songSelected )
        self.songList.setSelectionModel(selectionModel)
        #End songList


    # called when item is selected from Song Table View
    def songSelected(self, selected, deselected):
        print "Selected Song ID: ", self.songModel.getSongId(selected.row())


    def SetDb(self, fileName):
        self.db = Database(fileName, True)
        self.db.OpenCursor()


    def UpdateArtists(self):
        self.artistList.clear()

        result = self.db.ExecuteSql("""select artist from library 
                        group by artist order by artist""")

        self.artistList.addItem("<ALL ARTISTS>")

        for row in result:
            if row[0]:
                self.artistList.addItem(row[0])

        self.artistList.setCurrentRow(0)

    @QtCore.pyqtSlot()
    def UpdateAlbums(self):
        artistName = self.artistList.currentItem().text() 
        self.albumList.clear()

        self.albumList.addItem("<ALL ALBUMS>")

        result = None

        if artistName != "<ALL ARTISTS>":
            result = self.db.ExecuteSql("""select album from library 
                        where artist = "%s" 
                        group by album order by album"""%artistName)
        else:
            result = self.db.ExecuteSql("""select album from library 
                        group by album order by album""")

        for row in result:
            if row[0]:
                self.albumList.addItem(row[0])

        self.albumList.setCurrentRow(0)


    @QtCore.pyqtSlot()
    def UpdateTitles(self):
        artistName = self.artistList.currentItem().text() 
        albumName = self.albumList.currentItem().text() 

        self.songModel.clear()

        # Build SQL Query to handle <ALL*>
        result = None
        query = "select title, artist, album, genre, songid from library "
        queryToCount = "select count(*) from library "
        data = [] 
        prevWhereExist = False    #Check if where already exists

        if artistName != "<ALL ARTISTS>":
            query += """where artist = "%s" """
            queryToCount += """where artist = "%s" """
            prevWhereExist = True
            data.append(artistName)

        if albumName != "<ALL ALBUMS>":
            if prevWhereExist:
                query += "and "
                queryToCount += "and "
            else:
                query += "where "
                queryToCount += "where "
            queryToCount += """album = "%s" """
            query += """album = "%s" """
            data.append(albumName)

        data = tuple(data)

        # End Query Building

        # Execute SQL to Count rows Now
        # Adding separate count to make insertRows() call to 
        # songModel more efficient, as calling it everytime 
        # iterating through main result makes it slow and 
        # program irresponsive.

        resultCount = self.db.ExecuteSql(queryToCount%data)
        resultCountInt = 0

        resultCountInt = [row[0] for row in resultCount][0] 
        
        # Execute SQL to get result
        result = self.db.ExecuteSql(query%data)

        # Insert Result Into Song Table
        self.songModel.insertRows(self.songModel.rowCount(), resultCountInt,
                        QtCore.QModelIndex() )

        i = 0
        for row in result:
            self.songModel.setRow(i, row)
            i += 1

